<% include("comm/header.html"){} %>
<h1>通信协议</h1>
<ol>
    <li>
        普通HTTP接口采用Content-Type: application/json; charset=UTF-8<br/>
        H5跳转页接口采用Content-Type: application/x-www-form-urlencoded; charset=UTF-8<br/>
        上传文件接口采用Content-Type: multipart/form-data; boundary=ABCDEF; charset=UTF-8
    </li>
    <li>
        合作侧通知类接口为http://ip:port/notify?data=JSON密文，开放平台接口的公共参数描述见下文<br/>
        <ul type="disc">
            <li>version=2.0表示报文只签名不加密，此时通过公参的signType进行签名计算sign，且提交接口就是普通的Form表单，非JSON，但应答的是JSON</li>
            <li>
                version=2.1表示报文只加密不签名，加密后通过公参的data传输密文，应答报文中data域也为密文<br/>
                &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;除文件上传和H5跳转页接口为Form表单提交外，其余接口请求参数均为JSON格式；除文件下载和H5跳转页接口为各自独立的应答外，其余接口应答参数均为JSON格式
            </li>
            <li>
                version=2.2表示报文采用<span style="color:blue; font-weight:bold;">RSA</span>算法，加密后仍通过公参sign和data传输签名和密文，应答报文中sign和data域分别签名和密文<br/>
                &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;除文件上传和H5跳转页接口为Form表单提交外，其余接口请求参数均为JSON格式；除文件下载和H5跳转页接口为各自独立的应答外，其余接口应答参数均为JSON格式
            </li>
            <li>
                version=2.3表示报文<span style="color:blue; font-weight:bold;">AES+RSA</span>算法，加密后仍通过公参data传输密文，应答报文中data域也为密文<br/>
                &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;除文件上传和H5跳转页接口为Form表单提交外，其余接口请求参数均为JSON格式；除文件下载和H5跳转页接口为各自独立的应答外，其余接口应答参数均为JSON格式
            </li>
            <li>注：接口需要识别合作方，且公参无敏感信息，故公参不参与加密，只加密接口请求应答参数</li>
        </ul>
    </li>
    <li>
        测试环境地址为：https://jadyer.cn/open/router/rest<br/>
        生产环境地址为：https://jadyer.cn/open/router/rest<br/>
        <font color="blue">注①：H5地址为：https://jadyer.cn/open/router/rest/h5</font><br/>
        <font color="green">注②：连接生产环境，合作方需提供客户端IP，开放平台将其纳入白名单</font><br/>
        <font color="#FF00FF">注③：接口日调用次数限制，目前后台统一配置为999,999,999，等于未做限制</font>
    </li>
</ol>
<h1>签名机制</h1>
<ol type="1">
    <li>只有公共参数中version=2.0时才会启用该机制</li>
    <li>
        各接口中，只有传输了的参数才会参与签名，即便传的参数值是空的<br/>
        服务端会根据参数名称（除sign和文件流），将所有请求参数按字母先后顺序排序：key11value11...key33value33<br/>
        例如：foo=11，bar=22，baz=33排序为bar=22，baz=33，foo=11，参数名和值拼接后得到字符串bar22baz33foo11
    </li>
    <li>
        支持MD5签名方式，测试环境密钥appsecret=QQRif23NDzEd9aEQTAY6Dg，这里以测试环境举例<br/>
        将上一步的bar22baz33foo11后加上appsecret，得到字符串bar22baz33foo11QQRif23NDzEd9aEQTAY6Dg<br/>
        对其签名后得到值为小写的c8e71f9fe73a2b28e38a600570772c7a，便为公共参数中sign的值
    </li>
</ol>
<h1>加密模式AES</h1>
<ol type="1">
    <li>只有公共参数中version=2.1时才会启用该机制</li>
    <li>
        目前采用AES/ECB/PKCS5Padding模式加密，测试环境密钥appsecret=QQRif23NDzEd9aEQTAY6Dg<br/>
        加解密工具类可使用我的Github中的CodecUtil#buildAESEncrypt()和buildAESDecrypt()<br/>
        <a target="_blank" href="https://github.com/jadyer/seed/blob/master/seed-comm/src/main/java/com/jadyer/seed/comm/util/CodecUtil.java">https://github.com/jadyer/seed/blob/master/seed-comm/src/main/java/com/jadyer/seed/comm/util/CodecUtil.java</a>
    </li>
    <li>
        加密明文为各接口入参出参的所有不包括文件流和公共请求参数的JSON字符串<br/>
        例如表单域foo=11，bar=22，baz=””，明文字符串为dataPlain={"bar":"22","baz":"","foo":"11"}<br/>
        则其密文即data=vOpbyIQXrv3kLSz1i7U5v57zWjTk-PiAsHY3tTzv0ewk0tdKiSP-FYAS_EDhX7Db
    </li>
</ol>
<h1>加密模式RSA</h1>
<ol type="1">
    <li>只有公共参数中version=2.2时才会启用该机制</li>
    <li>
        RSA密钥位数为2048bit（1024已经不安全了），RSA签名算法采用SHA256WithRSA（SHA1WithRSA已被废弃），密文及签名的结果均采用Base64编码传输<br/>
        加解密（公钥加密，私钥解密）和签名（私钥签名，公钥验签）的工具类可使用我的Github中的CodecUtil#buildRSA的相关方法<br/>
        <a target="_blank" href="https://github.com/jadyer/seed/blob/master/seed-comm/src/main/java/com/jadyer/seed/comm/util/CodecUtil.java">https://github.com/jadyer/seed/blob/master/seed-comm/src/main/java/com/jadyer/seed/comm/util/CodecUtil.java</a>
    </li>
    <li>
        加解密和签名的明文为各接口入参出参的所有不包括文件流和公共请求参数的JSON字符串<br/>
        例如表单域foo=11，bar=22，baz=””，明文字符串为dataPlain={"bar":"22","baz":"","foo":"11"}
    </li>
</ol>
<h1>混合模式AES+RSA</h1>
<ol type="1">
    <li>只有公共参数中version=2.3时才会启用该机制</li>
    <li>
        此时加解密模式为<span style="color:blue; font-weight:bold;">AES+RSA</span>算法，其中AES仍采用AES/ECB/PKCS5Padding模式加密，RSA密钥位数仍为2048bit，RSA签名算法仍采用SHA256WithRSA<br/>
        加解密（公钥加密，私钥解密）和签名（私钥签名，公钥验签）的工具类可使用我的Github中的CodecUtil#buildAES和buildRSA的相关方法<br/>
        <a target="_blank" href="https://github.com/jadyer/seed/blob/master/seed-comm/src/main/java/com/jadyer/seed/comm/util/CodecUtil.java">https://github.com/jadyer/seed/blob/master/seed-comm/src/main/java/com/jadyer/seed/comm/util/CodecUtil.java</a>
    </li>
    <li>
        加解密和签名的明文为各接口入参出参的所有不包括文件流和公共请求参数的JSON字符串<br/>
        例如表单域foo=11，bar=22，baz=””，明文字符串为dataPlain={"bar":"22","baz":"","foo":"11"}<br/>
        假设AES密钥为QQRif23NDzEd9aEQTAY6Dg，则dataPlain加密后的密文data=vOpbyIQXrv3kLSz1i7U5v57zWjTk-PiAsHY3tTzv0ewk0tdKiSP-FYAS_EDhX7Db<br/>
        <span style="color:blue; font-weight:bold;">AES+RSA</span>具体交互方式如下：<br/>
        <ul type="disc">
            <li>服务端(Server)和客户端(Client)分别生成自己的RSA密钥对，并交换RSA公钥</li>
            <li>Client使用自己的RSA私钥签名请求dataPlain，便得到了公共请求参数中的签名值sign</li>
            <li>Client生成新的AES-Key并用它来加密dataPlain，便得到了公共请求参数中的密文data</li>
            <li>Client使用Server的RSA公钥加密AES-Key，便得到了公共请求参数中的signType（通过它来传输AES密钥的密文）</li>
        </ul>
        Server收到消息后,将上面的4个步骤反过来即可得到明文
    </li>
</ol>
<h1>公共参数</h1>
<ol type="1">
    <li>
        <h2>公共请求参数</h2>
        <table width="1260" border="0" cellspacing="1" bgcolor="#000000">
            <tr bgcolor="#8CB3E2">
                <th width="20%">名称</th>
                <th width="10%" align="center">类型</th>
                <th width="5%" align="center">必传</th>
                <th width="65%">说明</th>
            </tr>
            <tr bgcolor="#F0F0F0">
                <td>method</td>
                <td align="center">VARCHAR2(32)</td>
                <td align="center">Y</td>
                <td>API接口名称</td>
            </tr>
            <tr bgcolor="#F0F0F0">
                <td>version</td>
                <td align="center">CHAR(3)</td>
                <td align="center">Y</td>
                <td>API协议版本，暂时支持：2.1和2.2</td>
            </tr>
            <tr bgcolor="#F0F0F0">
                <td>appid</td>
                <td align="center">VARCHAR2(32)</td>
                <td align="center">Y</td>
                <td>分配给合作方的用于识别合作方身份的appid（同时会分配appsecret作为密钥）</td>
            </tr>
            <tr bgcolor="#F0F0F0">
                <td>timestamp</td>
                <td align="center">CHAR(19)</td>
                <td align="center">Y</td>
                <td>时间戳，格式为yyyy-MM-dd HH:mm:ss，服务端允许客户端请求最大时间误差为10分钟</td>
            </tr>
            <tr bgcolor="#F0F0F0">
                <td>signType</td>
                <td align="center">VARCHAR2(512)</td>
                <td align="center">N</td>
                <td>签名的摘要算法，可选值：小写的md5，version=2.0时必传</td>
            </tr>
            <tr bgcolor="#F0F0F0">
                <td>sign</td>
                <td align="center">VARCHAR2(512)</td>
                <td align="center">N</td>
                <td>签名结果字符串，version=2.0和2.2时必传</td>
            </tr>
            <tr bgcolor="#F0F0F0">
                <td>data</td>
                <td align="center">VARCHAR2(999)</td>
                <td align="center">N</td>
                <td>各接口的请求参数加密后的密文，version=2.1时必传</td>
            </tr>
        </table>
    </li>
    <li>
        <h2>应答报文结构</h2>
        <table width="1260" border="0" cellspacing="1" bgcolor="#000000">
            <tr bgcolor="#8CB3E2">
                <th width="20%">名称</th>
                <th width="10%" align="center">类型</th>
                <th width="5%" align="center">必传</th>
                <th width="65%">说明</th>
            </tr>
            <tr bgcolor="#F0F0F0">
                <td>code</td>
                <td align="center">VARCHAR2(3)</td>
                <td align="center">Y</td>
                <td>应答码，见附录 C</td>
            </tr>
            <tr bgcolor="#F0F0F0">
                <td>msg</td>
                <td align="center">VARCHAR2(512)</td>
                <td align="center">Y</td>
                <td>应答码描述</td>
            </tr>
            <tr bgcolor="#F0F0F0">
                <td>sign</td>
                <td align="center">VARCHAR2(512)</td>
                <td align="center">N</td>
                <td>签名结果字符串，通常只有code=0且version=2.2时该域才会有值</td>
            </tr>
            <tr bgcolor="#F0F0F0">
                <td>data</td>
                <td align="center">VARCHAR2(999)<T></td>
                <td align="center">N</td>
                <td>见各接口的应答报文结构，通常只有code=0时该域才会有值，且为密文</td>
            </tr>
        </table>
    </li>
</ol>
<% include("comm/footer.html"){} %>